package com.ukefu.webim.util;

import static org.elasticsearch.index.query.QueryBuilders.termQuery;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipOutputStream;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaBuilder.In;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.ui.ModelMap;

import com.ukefu.core.UKDataContext;
import com.ukefu.util.IP;
import com.ukefu.util.IPTools;
import com.ukefu.util.UCKeFuThreadFactory;
import com.ukefu.util.UKTools;
import com.ukefu.util.es.SearchTools;
import com.ukefu.util.es.UKDataBean;
import com.ukefu.util.mobile.MobileAddress;
import com.ukefu.util.mobile.MobileNumberUtils;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.repository.CallAgentRepository;
import com.ukefu.webim.service.repository.CallCenterSkillRepository;
import com.ukefu.webim.service.repository.CallOutFilterRepository;
import com.ukefu.webim.service.repository.CallOutNamesHisRepository;
import com.ukefu.webim.service.repository.CallOutNamesRepository;
import com.ukefu.webim.service.repository.CallOutRoleRepository;
import com.ukefu.webim.service.repository.CallOutTaskRepository;
import com.ukefu.webim.service.repository.CallcenterSipTrunkDynamicRepository;
import com.ukefu.webim.service.repository.CalloutSaleCountRepository;
import com.ukefu.webim.service.repository.ContactsItemAuthorizeRepository;
import com.ukefu.webim.service.repository.ContactsItemRepository;
import com.ukefu.webim.service.repository.ExtentionRepository;
import com.ukefu.webim.service.repository.FormFilterRepository;
import com.ukefu.webim.service.repository.JobDetailRepository;
import com.ukefu.webim.service.repository.NumberPoolRepository;
import com.ukefu.webim.service.repository.OrganRepository;
import com.ukefu.webim.service.repository.PbxHostRepository;
import com.ukefu.webim.service.repository.SaleStatusRepository;
import com.ukefu.webim.service.repository.SipTrunkRepository;
import com.ukefu.webim.service.repository.UserRepository;
import com.ukefu.webim.service.repository.UserRoleRepository;
import com.ukefu.webim.web.model.CallAgent;
import com.ukefu.webim.web.model.CallCenterSkill;
import com.ukefu.webim.web.model.CallOutFilter;
import com.ukefu.webim.web.model.CallOutNames;
import com.ukefu.webim.web.model.CallOutNamesHis;
import com.ukefu.webim.web.model.CallOutRole;
import com.ukefu.webim.web.model.CallOutTask;
import com.ukefu.webim.web.model.CallcenterSipTrunkDynamic;
import com.ukefu.webim.web.model.CalloutSaleCount;
import com.ukefu.webim.web.model.ContactsItem;
import com.ukefu.webim.web.model.ContactsItemAuthorize;
import com.ukefu.webim.web.model.Extention;
import com.ukefu.webim.web.model.FormFilter;
import com.ukefu.webim.web.model.JobDetail;
import com.ukefu.webim.web.model.NumberPool;
import com.ukefu.webim.web.model.Organ;
import com.ukefu.webim.web.model.PbxHost;
import com.ukefu.webim.web.model.SaleStatus;
import com.ukefu.webim.web.model.SipTrunk;
import com.ukefu.webim.web.model.StatusEvent;
import com.ukefu.webim.web.model.SysDic;
import com.ukefu.webim.web.model.UKeFuDic;
import com.ukefu.webim.web.model.User;
import com.ukefu.webim.web.model.UserRole;

public class CallCenterUtils {

	static final Executor fastExecutor = new ThreadPoolExecutor(
	          50,
	          100,
	          10, TimeUnit.SECONDS, // terminate idle threads after 10 sec
	          new SynchronousQueue<Runnable>()  // directly hand off tasks
	          , new UCKeFuThreadFactory("callcenterVoiceRecord")
	  );

	/**
	 *
	 * @param user
	 * @param orgi
	 * @param id
	 * @param service
	 * @return
	 * @throws Exception
	 */
	public static SipTrunk siptrunk(String extno ,String orgi, SipTrunkRepository sipTrunkRes, ExtentionRepository extRes, String phonenumber){
		SipTrunk sipTrunk = null;
		List<Extention> extList = extRes.findByExtentionAndOrgi(extno, orgi) ;
		if(extList.size() > 0){
			Extention ext = extList.get(0) ;
			if(!StringUtils.isBlank(ext.getSiptrunk())) {
				sipTrunk = (SipTrunk) CacheHelper.getSystemCacheBean().getCacheObject(ext.getSiptrunk(), ext.getOrgi()) ;
				if(sipTrunk == null) {
					//NOTE 多租户下 网关使用系统租户的
					sipTrunk = sipTrunkRes.findByIdAndOrgi(ext.getSiptrunk(), UKDataContext.SYSTEM_ORGI/*ext.getOrgi()*/) ;
					if(sipTrunk!=null) {
						CacheHelper.getSystemCacheBean().put(sipTrunk.getId() ,sipTrunk , ext.getOrgi()) ;
					}
				}
			}else {
				//NOTE 多租户下 网关使用系统租户的
				List<SipTrunk> sipTrunkList = sipTrunkRes.findByDefaultsipAndOrgi(true,UKDataContext.SYSTEM_ORGI/* ext.getOrgi()*/) ;
				if(sipTrunkList.size() > 0) {
					sipTrunk = sipTrunkList.get(0) ;
				}
			}
			if(sipTrunk!=null && sipTrunk.isDynamic() && !StringUtils.isBlank(phonenumber)) {
				sipTrunk = getDynamicSipTrunk(sipTrunk, sipTrunkRes, phonenumber) ;
			}
		}
		return sipTrunk;
	}
	
	public static SipTrunk siptrunk(String name ,String orgi, SipTrunkRepository sipTrunkRes , String phonenumber){
		SipTrunk sipTrunk = getSipTrunk(name, orgi , sipTrunkRes);
		if(sipTrunk!=null && sipTrunk.isDynamic() && !StringUtils.isBlank(phonenumber)) {
			sipTrunk = getDynamicSipTrunk(sipTrunk, sipTrunkRes, phonenumber) ;
		}
		return sipTrunk;
	}
	
	/**
	 * 动态SIP Trunk，根据归属地查找SIP Trunk
	 * @param sipTrunk
	 * @param sipTrunkRes
	 * @param phonenumber
	 * @return
	 */
	private static SipTrunk getDynamicSipTrunk(SipTrunk sipTrunk , SipTrunkRepository sipTrunkRes , String phonenumber) {
		SipTrunk retSipTrunk = sipTrunk ;
		if(sipTrunk!=null && sipTrunk.isDynamic() && !StringUtils.isBlank(phonenumber)) {
			CallcenterSipTrunkDynamicRepository dynamicRes = UKDataContext.getContext().getBean(CallcenterSipTrunkDynamicRepository.class) ;
			MobileAddress address = MobileNumberUtils.getAddress(phonenumber) ;
			if(dynamicRes!=null && address!=null && !StringUtils.isBlank(address.getAdmincode())) {
				List<CallcenterSipTrunkDynamic> sips = dynamicRes.findBySiptrunkidAndAreaAndHostidAndOrgi(sipTrunk.getId(), address.getAdmincode(), sipTrunk.getHostid(), sipTrunk.getOrgi()) ;
				if(sips!=null && sips.size() > 0) {
					CallcenterSipTrunkDynamic dynamicSip = sips.get(0) ;
					if(dynamicSip!=null && !StringUtils.isBlank(dynamicSip.getGatewayid())) {
						SipTrunk tempSipTrunk = getSipTrunk(dynamicSip.getGatewayid(), dynamicSip.getOrgi(), sipTrunkRes) ;
						if(tempSipTrunk!=null) {
							retSipTrunk = tempSipTrunk ;
						}
					}
				}
			}
		}
		return retSipTrunk ;
	}
	
	/**
	 * 根据ID或名称查找SIPTRUNK
	 * @param name
	 * @param orgi
	 * @param sipTrunkRes
	 * @return
	 */
	private static SipTrunk getSipTrunk(String name ,String orgi, SipTrunkRepository sipTrunkRes) {
		SipTrunk sipTrunk = null;
		if(StringUtils.isBlank(name)) {
			name = UKDataContext.SYSTEM_ORGI ;
		}
		if((sipTrunk = (SipTrunk) CacheHelper.getSystemCacheBean().getCacheObject(name, orgi)) == null) {
			List<SipTrunk> sipTrunkList = sipTrunkRes.findByNameAndOrgi(name,orgi) ;
			if(sipTrunkList.size() > 0){
				sipTrunk = sipTrunkList.get(0) ;
			}else {
				sipTrunk = sipTrunkRes.findByIdAndOrgi(name,orgi) ;
				if(sipTrunk == null) {
					sipTrunkList = sipTrunkRes.findByDefaultsipAndOrgi(true,orgi) ;
					if(sipTrunkList.size() > 0) {
						sipTrunk = sipTrunkList.get(0) ;
					}
				}
			}
			if(sipTrunk != null) {
				CacheHelper.getSystemCacheBean().put(sipTrunk.getId() ,sipTrunk , sipTrunk.getOrgi()) ;
			}
		}
		return sipTrunk;
	}

	/**
	 *
	 * @param user
	 * @param orgi
	 * @param id
	 * @param service
	 * @return
	 * @throws Exception
	 */
	public static PbxHost pbxhost(String ip){
		PbxHost pbxHost =  (PbxHost) CacheHelper.getSystemCacheBean().getCacheObject(ip, UKDataContext.SYSTEM_ORGI) ;
		if(pbxHost == null) {
			PbxHostRepository pbxHostRes = UKDataContext.getContext().getBean(PbxHostRepository.class) ;
			List<PbxHost> pbxHostList = pbxHostRes.findByHostnameOrIpaddr(ip, ip) ;
			if(pbxHostList!=null && pbxHostList.size() > 0) {
				pbxHost = pbxHostList.get(0) ;
				CacheHelper.getSystemCacheBean().put(pbxHost.getIpaddr() ,pbxHost , pbxHost.getOrgi()) ;
			}
		}
		return pbxHost;
	}


	/**
	 *
	 * @param user
	 * @param orgi
	 * @param id
	 * @param service
	 * @return
	 * @throws Exception
	 */
	public static SipTrunk siptrunk(String name ,String orgi, SipTrunkRepository sipTrunkRes){
		SipTrunk sipTrunk = null;
		if(StringUtils.isBlank(name)) {
			name = UKDataContext.SYSTEM_ORGI ;
		}
		if((sipTrunk = (SipTrunk) CacheHelper.getSystemCacheBean().getCacheObject(name, orgi)) == null) {
			List<SipTrunk> sipTrunkList = sipTrunkRes.findByNameAndOrgi(name,orgi) ;
			if(sipTrunkList.size() > 0){
				sipTrunk = sipTrunkList.get(0) ;
			}else {
				sipTrunkList = sipTrunkRes.findByDefaultsipAndOrgi(true,orgi) ;
				if(sipTrunkList.size() > 0) {
					sipTrunk = sipTrunkList.get(0) ;
				}
			}
			if(sipTrunk != null) {
				CacheHelper.getSystemCacheBean().put(sipTrunk.getId() ,sipTrunk , sipTrunk.getOrgi()) ;
			}
		}
		return sipTrunk;
	}

	/**
	 *
	 * @param user
	 * @param orgi
	 * @param id
	 * @param service
	 * @return
	 * @throws Exception
	 */
	public static SipTrunk siptrunk(String name ,String orgi){
		SipTrunk sipTrunk = null;
		SipTrunkRepository sipTrunkRes = UKDataContext.getContext().getBean(SipTrunkRepository.class) ;
		if((sipTrunk = (SipTrunk) CacheHelper.getSystemCacheBean().getCacheObject(name, orgi)) == null) {
			List<SipTrunk> sipTrunkList = sipTrunkRes.findByNameAndOrgi(name,orgi) ;
			if(sipTrunkList.size() > 0){
				sipTrunk = sipTrunkList.get(0) ;
			}
			if(sipTrunk != null) {
				CacheHelper.getSystemCacheBean().put(sipTrunk.getId() ,sipTrunk , sipTrunk.getOrgi()) ;
			}
		}
		return sipTrunk;
	}

	/**
	 * 我的部门以及授权给我的部门
	 * @param userRoleRes
	 * @param callOutRoleRes
	 * @param user
	 * @return
	 */
	public static List<String> getAuthOrgan(UserRoleRepository userRoleRes , CallOutRoleRepository callOutRoleRes,User user){
		List<UserRole> userRole = userRoleRes.findByOrgiAndUser(user.getOrgi(), user);
		ArrayList<String> organList = new ArrayList<String>();
		if (userRole.size() > 0) {
			for (UserRole userTemp : userRole) {
				CallOutRole roleOrgan = callOutRoleRes.findByOrgiAndRoleid(user.getOrgi(),
						userTemp.getRole().getId());
				if (roleOrgan != null) {
					if (!StringUtils.isBlank(roleOrgan.getOrganid())) {
						String[] organ = roleOrgan.getOrganid().split(",");
						for (int i = 0; i < organ.length; i++) {
							organList.add(organ[i]);
						}

					}
				}
			}
		}

		if(user!=null && !StringUtils.isBlank(user.getOrgan())) {
			organList.add(user.getOrgan()) ;
		}
		return organList ;
	}
	/**
	 * 我的部门以及授权给我的部门 - 批次
	 * @param batchRes
	 * @param userRoleRes
	 * @param callOutRoleRes
	 * @param user
	 * @return
	 */
	public static List<JobDetail> getBatchList(JobDetailRepository batchRes,UserRoleRepository userRoleRes , CallOutRoleRepository callOutRoleRes, final User user){

		//final List<String> organList = CallCenterUtils.getAuthOrgan(userRoleRes, callOutRoleRes, user);

		final List<String> organList = CallCenterUtils.getExistOrgan(user);

		List<JobDetail> batchList = batchRes.findAll(new Specification<JobDetail>(){
			@Override
			public Predicate toPredicate(Root<JobDetail> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				In<Object> in = cb.in(root.get("organ"));

				list.add(cb.equal(root.get("orgi").as(String.class), user.getOrgi()));
				list.add(cb.equal(root.get("tasktype").as(String.class), UKDataContext.TaskType.BATCH.toString()));

				if(organList.size() > 0){

					for(String id : organList){
						in.value(id) ;
					}
				}else{
					in.value(UKDataContext.UKEFU_SYSTEM_NO_DAT) ;
				}
				list.add(in) ;

				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}});

		return batchList;
	}
	/**
	 * 我的部门以及授权给我的部门 - 筛选表单
	 * @param filterRes
	 * @param userRoleRes
	 * @param callOutRoleRes
	 * @param user
	 * @return
	 */
	public static List<FormFilter> getFormFilterList(FormFilterRepository filterRes,UserRoleRepository userRoleRes , CallOutRoleRepository callOutRoleRes, final User user){

		//final List<String> organList = CallCenterUtils.getAuthOrgan(userRoleRes, callOutRoleRes, user);

		final List<String> organList = CallCenterUtils.getExistOrgan(user);

		List<FormFilter> formFilterList = filterRes.findAll(new Specification<FormFilter>(){
			@Override
			public Predicate toPredicate(Root<FormFilter> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				In<Object> in = cb.in(root.get("organ"));

				list.add(cb.equal(root.get("orgi").as(String.class), user.getOrgi()));

				if(organList.size() > 0){

					for(String id : organList){
						in.value(id) ;
					}
				}else{
					in.value(UKDataContext.UKEFU_SYSTEM_NO_DAT) ;
				}
				list.add(in) ;

				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}});

		return formFilterList;
	}

	/**
	 * 我的部门以及授权给我的部门 - 活动
	 * @param batchRes
	 * @param userRoleRes
	 * @param callOutRoleRes
	 * @param user
	 * @return
	 */
	public static List<JobDetail> getActivityList(JobDetailRepository batchRes,UserRoleRepository userRoleRes , CallOutRoleRepository callOutRoleRes,final User user){

		//final List<String> organList = CallCenterUtils.getAuthOrgan(userRoleRes, callOutRoleRes, user);

		final List<String> organList = CallCenterUtils.getExistOrgan(user);

		List<JobDetail> activityList = batchRes.findAll(new Specification<JobDetail>(){
			@Override
			public Predicate toPredicate(Root<JobDetail> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				In<Object> in = cb.in(root.get("organ"));

				list.add(cb.equal(root.get("orgi").as(String.class), user.getOrgi()));
				list.add(cb.equal(root.get("tasktype").as(String.class), UKDataContext.TaskType.ACTIVE.toString()));

				if(organList.size() > 0){

					for(String id : organList){
						in.value(id) ;
					}
				}else{
					in.value(UKDataContext.UKEFU_SYSTEM_NO_DAT) ;
				}
				list.add(in) ;

				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}});

		return activityList;
	}
	/**
	 * 查询条件，下拉信息返回
	 * @param map
	 * @param user
	 * @param ownerdept
	 * @param actid
	 */
	public static void getAllCallOutList(ModelMap map, final User user,String ownerdept, String actid){
		JobDetailRepository batchRes = UKDataContext.getContext().getBean(JobDetailRepository.class) ;
		UserRoleRepository userRoleRes = UKDataContext.getContext().getBean(UserRoleRepository.class) ;
		CallOutRoleRepository callOutRoleRes = UKDataContext.getContext().getBean(CallOutRoleRepository.class) ;
		FormFilterRepository filterRes = UKDataContext.getContext().getBean(FormFilterRepository.class) ;
		OrganRepository organRes = UKDataContext.getContext().getBean(OrganRepository.class) ;
		SaleStatusRepository saleStatusRes = UKDataContext.getContext().getBean(SaleStatusRepository.class);

		List<JobDetail> activityList = CallCenterUtils.getActivityList(batchRes,userRoleRes, callOutRoleRes,user);
		final List<String> actidList = new ArrayList<String>();
		for(JobDetail act :activityList){
			actidList.add(act.getDicid());
		}
		List<SaleStatus> salestatusList = saleStatusRes.findAll(new Specification<SaleStatus>(){
			@Override
			public Predicate toPredicate(Root<SaleStatus> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				In<Object> in = cb.in(root.get("activityid"));

				list.add(cb.equal(root.get("orgi").as(String.class), user.getOrgi()));

				if(actidList.size() > 0){
					for(String id : actidList){
						in.value(id) ;
					}
				}else{
					in.value(UKDataContext.UKEFU_SYSTEM_NO_DAT) ;
				}
				list.add(in) ;

				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}});
		map.put("salestatusList", salestatusList);
		map.put("batchList", CallCenterUtils.getBatchList(batchRes, userRoleRes, callOutRoleRes,user));
		map.put("activityList", CallCenterUtils.getActivityList(batchRes,userRoleRes, callOutRoleRes,user));
		map.put("formFilterList", CallCenterUtils.getFormFilterList(filterRes,userRoleRes, callOutRoleRes,user));
		if(StringUtils.isBlank(ownerdept)){

			map.addAttribute("owneruserList",UKDataContext.getContext().getBean(UserRepository.class).findByOrganAndDatastatusAndOrgi(UKDataContext.UKEFU_SYSTEM_NO_DAT, false, user.getOrgi()));
		}else{
			map.addAttribute("owneruserList",UKDataContext.getContext().getBean(UserRepository.class).findByOrganAndDatastatusAndOrgi(ownerdept, false, user.getOrgi()));

		}
		map.addAttribute("skillList", organRes.findAll(CallCenterUtils.getAuthOrgan(userRoleRes, callOutRoleRes, user)));
		map.put("taskList",UKDataContext.getContext().getBean(CallOutTaskRepository.class).findByActidAndOrgi(actid, user.getOrgi()));
		map.put("allUserList",UKDataContext.getContext().getBean(UserRepository.class).findByOrgiAndDatastatus(user.getOrgi(), false));
		//JobDetail act = batchRes.findByIdAndOrgi(actid, user.getOrgi());
		//if(act != null){
		//	map.put("salestatusList",UKDataContext.getContext().getBean(SaleStatusRepository.class).findByOrgiAndActivityid(user.getOrgi(), act.getDicid()));
		//}
		//机器人
		map.addAttribute("aiList",UKDataContext.getContext().getBean(ExtentionRepository.class).findByExtypeAndOrgi(UKDataContext.ExtentionType.IVR.toString() , user.getOrgi()));
		//队列
		map.addAttribute("forcastQueueList",UKDataContext.getContext().getBean(CallCenterSkillRepository.class).findByOrgi(user.getOrgi()));
		map.addAttribute("statusList",UKeFuDic.getInstance().getDic("com.dic.callout.activity"));
	}
	/**
	 * 指定活动，已设置的分配数
	 * @param map
	 * @param activityid
	 * @param user
	 */
	public static void getNamenum(ModelMap map,String activityid,User user){

		CallAgentRepository callAgentRes = UKDataContext.getContext().getBean(CallAgentRepository.class);

		List<CallAgent> actList = callAgentRes.findByOrgiAndActid(user.getOrgi(), activityid);
    	int namenum = 0;
    	if(actList.size() > 0 ){
    		for(CallAgent callAgent : actList){
    			if(callAgent.getDisnum() > 0){
    				namenum = namenum + callAgent.getDisnum();
    			}
    		}
    	}
    	map.put("namenum", namenum);
	}
	/**
	 * 查询目前存在的部门
	 * 已分配部门的坐席，如果部门被删之后，这个方法可以把这些用户过滤掉
	 * @param user
	 * @return
	 */
	public static List<String> getExistOrgan(User user){

		UserRoleRepository userRoleRes = UKDataContext.getContext().getBean(UserRoleRepository.class) ;
		CallOutRoleRepository callOutRoleRes = UKDataContext.getContext().getBean(CallOutRoleRepository.class) ;
		OrganRepository organRes = UKDataContext.getContext().getBean(OrganRepository.class) ;

		final List<String> organList = CallCenterUtils.getAuthOrgan(userRoleRes, callOutRoleRes, user);

		List<Organ> organAllList = organRes.findByOrgi(user.getOrgi());

		final List<String> tempList = new ArrayList<String>();
		if (user.isSuperuser()) {
			for(Organ organ : organAllList){
				tempList.add(organ.getId());
			}
		}else{
			for(String organid : organList){
				for(Organ organ : organAllList){
					if(organid.equals(organ.getId())){
						tempList.add(organid);
					}
				}
			}
			
			//判断所属部门是否有开启数据权限，若开启数据权限则能查看当前部门及以下部门的数据
			Organ currentOrgan = organRes.findByIdAndOrgi(user.getOrgan(), user.getOrgi());
			if (currentOrgan != null && currentOrgan.isDatauth()) {
				getChildrenOrgan(tempList,organAllList,currentOrgan.getId());
			}
		}
		
		return tempList ;
	}
	
	public static void getChildrenOrgan(List<String> tempList,List<Organ> organAllList,String currentorganid){
		for(Organ or: organAllList){
			if (!StringUtils.isBlank(or.getParent()) && or.getParent().equals(currentorganid)) {
				tempList.add(or.getId());
				getChildrenOrgan(tempList,organAllList,or.getId());
			}
		}
	}
	
	/**
	 * 分配给坐席的名单，单个名单，回收到池子
	 * @param task
	 * @param batch
	 * @param callOutFilter
	 */
	public static void getAgentRenum(CallOutTask task, JobDetail batch, CallOutFilter callOutFilter){

		CallOutTaskRepository callOutTaskRes = UKDataContext.getContext().getBean(CallOutTaskRepository.class) ;
		JobDetailRepository batchRes = UKDataContext.getContext().getBean(JobDetailRepository.class) ;
		CallOutFilterRepository callOutFilterRes = UKDataContext.getContext().getBean(CallOutFilterRepository.class) ;

		//修改，拨打任务
		if(task != null){
			task.setAssigned(task.getAssigned() - 1);//分配到坐席数
			task.setNotassigned(task.getNotassigned() + 1);//未分配数
			task.setRenum(task.getRenum() + 1);//回收到池子数
			callOutTaskRes.save(task);
		}

		//修改，批次
		if(batch != null){
			batch.setAssigned(batch.getAssigned() - 1);//已分配
			batch.setNotassigned(batch.getNotassigned() + 1);//未分配
			batchRes.save(batch);
		}

		//修改，筛选记录
		if(callOutFilter != null){
			callOutFilter.setAssigned(callOutFilter.getAssigned() - 1);//分配给坐席数
			callOutFilter.setRenum(callOutFilter.getRenum() + 1);//回收到池子数
			callOutFilter.setNotassigned(callOutFilter.getNotassigned() + 1);//未分配数
			callOutFilterRes.save(callOutFilter);
		}
	}

	/**
	 * 分配给坐席的名单，单个名单，回收到部门
	 * @param task
	 * @param callOutFilter
	 */
	public static void getAgentReorgannum(CallOutTask task, CallOutFilter callOutFilter){

		CallOutTaskRepository callOutTaskRes = UKDataContext.getContext().getBean(CallOutTaskRepository.class) ;
		CallOutFilterRepository callOutFilterRes = UKDataContext.getContext().getBean(CallOutFilterRepository.class) ;

		//修改，拨打任务
		if(task != null){
			task.setNotassigned(task.getNotassigned() + 1);//未分配数
			task.setAssignedorgan(task.getAssignedorgan() - 1);//分配到部门数
			task.setReorgannum(task.getReorgannum() + 1);//回收到部门数
			callOutTaskRes.save(task);
		}


		//修改，筛选记录
		if(callOutFilter != null){
			callOutFilter.setAssigned(callOutFilter.getAssigned() - 1);//分配给坐席数
			callOutFilter.setReorgannum(callOutFilter.getReorgannum() + 1);//回收到部门数
			callOutFilterRes.save(callOutFilter);
		}
	}

	/**
	 * 分配给部门的名单，单个名单，回收到池子
	 * @param task
	 * @param batch
	 * @param callOutFilter
	 */
	public static void getOrganRenum(CallOutTask task, JobDetail batch, CallOutFilter callOutFilter){

		CallOutTaskRepository callOutTaskRes = UKDataContext.getContext().getBean(CallOutTaskRepository.class) ;
		JobDetailRepository batchRes = UKDataContext.getContext().getBean(JobDetailRepository.class) ;
		CallOutFilterRepository callOutFilterRes = UKDataContext.getContext().getBean(CallOutFilterRepository.class) ;

		//修改，拨打任务
		if(task != null){
			task.setAssignedorgan(task.getAssignedorgan() - 1);//分配到部门数
			task.setNotassigned(task.getNotassigned() + 1);//未分配数
			task.setRenum(task.getRenum() + 1);//回收到池子数
			callOutTaskRes.save(task);
		}

		//修改，批次
		if(batch != null){
			batch.setAssigned(batch.getAssigned() - 1);//已分配
			batch.setNotassigned(batch.getNotassigned() + 1);//未分配
			batchRes.save(batch);
		}

		//修改，筛选记录
		if(callOutFilter != null){
			callOutFilter.setAssignedorgan(callOutFilter.getAssignedorgan() - 1);//分配到部门数
			callOutFilter.setRenum(callOutFilter.getRenum() + 1);//回收到池子数
			callOutFilter.setNotassigned(callOutFilter.getNotassigned() + 1);//未分配数
			callOutFilterRes.save(callOutFilter);
		}
	}

	/**
	 * 获取指定活动，已分配的名单数
	 * @param actid
	 * @param user
	 * @return
	 */
	public static int getActDisnum(@Valid String actid,User user, @Valid int p, @Valid int ps){
		BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
		queryBuilder.must(termQuery("actid", actid));// 活动ID
		queryBuilder.mustNot(termQuery("status", UKDataContext.NamesDisStatusType.NOT.toString()));
		PageImpl<UKDataBean> dataList = SearchTools.search(queryBuilder,p, 1);
		return (int)dataList.getTotalElements();
	}
	/**
	 * 获取语音渠道中的查询条件
	 * @param map
	 * @param orgi
	 */
	public static void getCallCenterSearch(ModelMap map,@Valid String orgi ,@Valid final String discaller , @Valid final String discalled 
    		, @Valid final String begin , @Valid final String end , @Valid final String direction, @Valid final String userid, @Valid final String organ
			,@Valid final String ringdurbegin ,@Valid final String ringdurend ,@Valid final String incallbegin ,@Valid final String incallend
    		,@Valid final String record ,@Valid final String misscall ,@Valid final String calltype,@Valid final String recordbegin,@Valid final String recordend){
		UserRepository userRes = UKDataContext.getContext().getBean(UserRepository.class) ;
		OrganRepository organRes = UKDataContext.getContext().getBean(OrganRepository.class) ;

		map.put("allUserList",userRes.findByOrgi(orgi));
		map.put("skillList",organRes.findByOrgi(orgi));
		
		map.addAttribute("discaller", discaller) ;
		map.addAttribute("discalled", discalled) ;
		map.addAttribute("begin", begin) ;
		map.addAttribute("end", end) ;
		map.addAttribute("organ", organ) ;
		map.addAttribute("userid", userid) ;
		
		map.addAttribute("ringdurbegin", ringdurbegin) ;
		map.addAttribute("ringdurend", ringdurend) ;
		map.addAttribute("incallbegin", incallbegin) ;
		map.addAttribute("incallend", incallend) ;
		map.addAttribute("record", record) ;
		map.addAttribute("misscall", misscall) ;
		map.addAttribute("calltype", calltype) ;
		map.addAttribute("recordbegin", recordbegin) ;
		map.addAttribute("recordend", recordend) ;
		
		CallCenterSkillRepository callCenterSkillRepository = UKDataContext.getContext().getBean(CallCenterSkillRepository.class);
		List<CallCenterSkill> callCenterSkillList = callCenterSkillRepository.findByOrgi(orgi);
		map.addAttribute("callCenterSkillList", callCenterSkillList) ;
	}

	public static void saveCallOutNamesHis(@Valid CallOutNames callOutNames, String type) {
		CallOutNamesHisRepository calloutRes = UKDataContext.getContext().getBean(CallOutNamesHisRepository.class);
		CallOutNamesHis callOutNamesHis = new CallOutNamesHis();
		callOutNamesHis.setActid(callOutNames.getActid());
		callOutNamesHis.setBatid(callOutNames.getBatid());
		callOutNamesHis.setBatname(callOutNames.getBatname());
		callOutNamesHis.setCalls(callOutNames.getCalls());
		callOutNamesHis.setCalltype(callOutNames.getCalltype());
		callOutNamesHis.setCreater(callOutNames.getCreater());
		callOutNamesHis.setCreatetime(new Date());
		callOutNamesHis.setDataid(callOutNames.getDataid());
		callOutNamesHis.setDatastatus(callOutNames.getDatastatus());
		callOutNamesHis.setDistype(callOutNames.getDistype());
		callOutNamesHis.setFaildcalls(callOutNames.getFaildcalls());
		callOutNamesHis.setFailed(callOutNames.isFailed());
		callOutNamesHis.setFilterid(callOutNames.getFilterid());
		callOutNamesHis.setFirstcallstatus(callOutNames.getFirstcallstatus());
		callOutNamesHis.setFirstcalltime(callOutNames.getFirstcalltime());
		callOutNamesHis.setInvalid(callOutNames.isInvalid());
		callOutNamesHis.setLeavenum(callOutNames.getLeavenum());

		callOutNamesHis.setMetaname(callOutNames.getMetaname());
		callOutNamesHis.setName(callOutNames.getName());

		callOutNamesHis.setOrgan(callOutNames.getOrgan());
		callOutNamesHis.setOrgi(callOutNames.getOrgi());
		callOutNamesHis.setOwnerdept(callOutNames.getOwnerdept());
		callOutNamesHis.setOwneruser(callOutNames.getOwneruser());
		callOutNamesHis.setPhonenumber(callOutNames.getPhonenumber());
		callOutNamesHis.setPreviewtime(callOutNames.getPreviewtime());
		callOutNamesHis.setPreviewtimes(callOutNames.getPreviewtimes());
		if(!StringUtils.isBlank(type)){
			if("reservation".equals(type)){
				callOutNamesHis.setReservation(callOutNames.isReservation());
				callOutNamesHis.setOptime(callOutNames.getOptime());
				callOutNamesHis.setMemo(callOutNames.getMemo());
				if(!"waste".equals(callOutNames.getStatus())){
					callOutNamesHis.setStatus(callOutNames.getStatus());
				}
			}else if("waste".equals(type)){
				callOutNamesHis.setStatus(callOutNames.getStatus());
				callOutNamesHis.setReservation(false);
				callOutNamesHis.setOptime(null);
				callOutNamesHis.setMemo(null);
			}
		}

		callOutNamesHis.setServicetype(callOutNames.getServicetype());

		callOutNamesHis.setTaskid(callOutNames.getTaskid());
		callOutNamesHis.setTaskname(callOutNames.getTaskname());
		callOutNamesHis.setUpdatetime(callOutNames.getUpdatetime());
		callOutNamesHis.setWorkstatus(callOutNames.getWorkstatus());

		calloutRes.save(callOutNamesHis);
	}

	public static void getCalloutCount(String orgi, String type,String dataid){
		CalloutSaleCountRepository calloutCountRes = UKDataContext.getContext().getBean(CalloutSaleCountRepository.class) ;
		CallOutNamesRepository callNameRes = UKDataContext.getContext().getBean(CallOutNamesRepository.class) ;
		calloutCountRes.deleteByOrgi(orgi);

		BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
		queryBuilder.must(termQuery("orgi",orgi));
		List<CalloutSaleCount> saleCountList = new ArrayList<>();
		PageImpl<UKDataBean> aggUserList = SearchTools.aggregation(queryBuilder,"owneruser", true, 0, 1);
		if(aggUserList.getContent().size() > 0){
			for(UKDataBean ukdata : aggUserList.getContent()){
				if(ukdata.getValues() != null){
					CalloutSaleCount userCount = new CalloutSaleCount();
					userCount.setOrgi(orgi);
					userCount.setCreatetime(new Date());
					userCount.setDataid(ukdata.getValues().get("id").toString());
					userCount.setType(UKDataContext.UKEFU_SYSTEM_DIS_AGENT);

					if(ukdata.getValues().get("total") != null){
						userCount.setNamenum(Integer.parseInt((ukdata.getValues().get("total").toString())));//分配总数
					}
					if(ukdata.getValues().get("callstatus.notcall") != null){
						userCount.setNotcall(Integer.parseInt((ukdata.getValues().get("callstatus.notcall").toString())));//未拨打
					}
					if(ukdata.getValues().get("callstatus.success") != null){
						userCount.setCallsuccess(Integer.parseInt((ukdata.getValues().get("callstatus.success").toString())));//拨打成功
					}
					if(ukdata.getValues().get("callstatus.faild") != null){
						userCount.setCallfaild(Integer.parseInt((ukdata.getValues().get("callstatus.faild").toString())));//拨打失败
					}
					if(ukdata.getValues().get("apstatus.false") != null){
						userCount.setApfalse(Integer.parseInt((ukdata.getValues().get("apstatus.false").toString())));//未预约
					}
					if(ukdata.getValues().get("apstatus.true") != null){
						userCount.setAptrue(Integer.parseInt((ukdata.getValues().get("apstatus.true").toString())));//已预约
					}
					saleCountList.add(userCount);
				}
			}

		}
		PageImpl<UKDataBean> aggOrganList = SearchTools.aggregation(queryBuilder,"ownerdept", true, 0, 1);
		if(aggOrganList.getContent().size() > 0){
			for(UKDataBean ukdata : aggOrganList.getContent()){
				CalloutSaleCount userCount = new CalloutSaleCount();
				userCount.setOrgi(orgi);
				userCount.setCreatetime(new Date());
				userCount.setDataid(ukdata.getValues().get("id").toString());
				userCount.setType(UKDataContext.UKEFU_SYSTEM_DIS_ORGAN);
				if(ukdata.getValues().get("total") != null){
					userCount.setNamenum(Integer.parseInt((ukdata.getValues().get("total").toString())));//分配总数
				}
				if(ukdata.getValues().get("callstatus.notcall") != null){
					userCount.setNotcall(Integer.parseInt((ukdata.getValues().get("callstatus.notcall").toString())));//未拨打
				}
				if(ukdata.getValues().get("callstatus.success") != null){
					userCount.setCallsuccess(Integer.parseInt((ukdata.getValues().get("callstatus.success").toString())));//拨打成功
				}
				if(ukdata.getValues().get("callstatus.faild") != null){
					userCount.setCallfaild(Integer.parseInt((ukdata.getValues().get("callstatus.faild").toString())));//拨打失败
				}
				if(ukdata.getValues().get("apstatus.false") != null){
					userCount.setApfalse(Integer.parseInt((ukdata.getValues().get("apstatus.false").toString())));//未预约
				}
				if(ukdata.getValues().get("apstatus.true") != null){
					userCount.setAptrue(Integer.parseInt((ukdata.getValues().get("apstatus.true").toString())));//已预约
				}
				saleCountList.add(userCount);
			}
		}
		PageImpl<UKDataBean> aggAiList = SearchTools.aggregation(queryBuilder,"ownerai", true, 0, 1);
		if(aggAiList.getContent().size() > 0){
			for(UKDataBean ukdata : aggAiList.getContent()){
				CalloutSaleCount userCount = new CalloutSaleCount();
				userCount.setOrgi(orgi);
				userCount.setCreatetime(new Date());
				userCount.setDataid(ukdata.getValues().get("id").toString());
				userCount.setType(UKDataContext.UKEFU_SYSTEM_DIS_ORGAN);
				if(ukdata.getValues().get("total") != null){
					userCount.setNamenum(Integer.parseInt((ukdata.getValues().get("total").toString())));//分配总数
				}
				if(ukdata.getValues().get("callstatus.notcall") != null){
					userCount.setNotcall(Integer.parseInt((ukdata.getValues().get("callstatus.notcall").toString())));//未拨打
				}
				if(ukdata.getValues().get("callstatus.success") != null){
					userCount.setCallsuccess(Integer.parseInt((ukdata.getValues().get("callstatus.success").toString())));//拨打成功
				}
				if(ukdata.getValues().get("callstatus.faild") != null){
					userCount.setCallfaild(Integer.parseInt((ukdata.getValues().get("callstatus.faild").toString())));//拨打失败
				}
				if(ukdata.getValues().get("apstatus.false") != null){
					userCount.setApfalse(Integer.parseInt((ukdata.getValues().get("apstatus.false").toString())));//未预约
				}
				if(ukdata.getValues().get("apstatus.true") != null){
					userCount.setAptrue(Integer.parseInt((ukdata.getValues().get("apstatus.true").toString())));//已预约
				}
				saleCountList.add(userCount);
			}
		}
		if(saleCountList.size() > 0){
			calloutCountRes.save(saleCountList);
		}
		if(!StringUtils.isBlank(type)){
			switch(type){
				case "user" :
					callNameRes.deleteByOrgiAndOwneruser(orgi,dataid);
					break ;
				case "data" :
					callNameRes.deleteByOrgiAndDataid(orgi, dataid);
					break ;
				case "batch" :
					callNameRes.deleteByOrgiAndBatid(orgi, dataid);
					break ;
				default :
					break;
			}
		}
	}

	/**
	 *
	 * @param userid
	 * @param orgi
	 */
	public static void getCalloutCount(String userid,String orgi){
		CalloutSaleCountRepository calloutCountRes = UKDataContext.getContext().getBean(CalloutSaleCountRepository.class) ;

		BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
		queryBuilder.must(termQuery("orgi",orgi));
		queryBuilder.must(termQuery(UKDataContext.UKEFU_SYSTEM_DIS_AGENT,userid));
		List<CalloutSaleCount> saleCountList = new ArrayList<>();
		PageImpl<UKDataBean> aggUserList = SearchTools.aggregation(queryBuilder,"owneruser", true, 0, 10000);
		if(aggUserList.getContent().size() > 0){
			for(UKDataBean ukdata : aggUserList.getContent()){
				if(ukdata.getValues() != null){
					CalloutSaleCount userCount = new CalloutSaleCount();
					userCount.setOrgi(orgi);
					userCount.setCreatetime(new Date());
					userCount.setDataid(ukdata.getValues().get("id").toString());
					userCount.setType(UKDataContext.UKEFU_SYSTEM_DIS_AGENT);

					if(ukdata.getValues().get("total") != null){
						userCount.setNamenum(Integer.parseInt((ukdata.getValues().get("total").toString())));//分配总数
					}
					if(ukdata.getValues().get("callstatus.notcall") != null){
						userCount.setNotcall(Integer.parseInt((ukdata.getValues().get("callstatus.notcall").toString())));//未拨打
					}
					if(ukdata.getValues().get("callstatus.success") != null){
						userCount.setCallsuccess(Integer.parseInt((ukdata.getValues().get("callstatus.success").toString())));//拨打成功
					}
					if(ukdata.getValues().get("callstatus.faild") != null){
						userCount.setCallfaild(Integer.parseInt((ukdata.getValues().get("callstatus.faild").toString())));//拨打失败
					}
					if(ukdata.getValues().get("apstatus.false") != null){
						userCount.setApfalse(Integer.parseInt((ukdata.getValues().get("apstatus.false").toString())));//未预约
					}
					if(ukdata.getValues().get("apstatus.true") != null){
						userCount.setAptrue(Integer.parseInt((ukdata.getValues().get("apstatus.true").toString())));//已预约
					}
					saleCountList.add(userCount);
				}
			}
		}

		List<CalloutSaleCount> countList = calloutCountRes.findByOrgiAndDataid(orgi , userid);
		if(countList.size() > 0){
			calloutCountRes.delete(countList);
		}
		if(saleCountList.size() > 0) {
			calloutCountRes.save(saleCountList) ;
		}
	}
	/**
	 * 批量打包语音文件 , 通过信号量控制最大不超过10个线程执行，将来增加配置参数来调整信号量
	 * @param statusEventList
	 * @return
	 * @throws Exception
	 */
	public static File packageVoiceFile(final List<StatusEvent> statusEventList) throws Exception {
		final Semaphore semaphore = new Semaphore(10);
		final AtomicInteger fetch = new AtomicInteger() ;	//用于计数的轮次，从0开始
		List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
		File tempFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), ".zip") ;
		final FileOutputStream fileOutputStream = new FileOutputStream(tempFile) ;
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream() ;
		final ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
		final List<File> recordFileList = new ArrayList<File>();
		try {
			final List<StatusEvent> tempArrayList = new ArrayList<StatusEvent>();
			tempArrayList.addAll(statusEventList) ;
			for(int i = 0 ; i< statusEventList.size() ; i++) {
				Callable<Integer> callable = new Callable<Integer>() {
					@Override
					public Integer call() throws Exception {
						StatusEvent temp = null;
						synchronized (tempArrayList) {
							if(tempArrayList.size() > 0) {
								temp = tempArrayList.remove(0) ;
							}
						}
						File tempVoiceRecordFile = null ;
						try {
							if(temp != null) {
								tempVoiceRecordFile = UKTools.crawlVoiceRecord(temp) ;
								if(tempVoiceRecordFile!=null && tempVoiceRecordFile.exists()) {
									recordFileList.add(tempVoiceRecordFile) ;
								}
							}
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							fetch.incrementAndGet();
							semaphore.release();
						}
						return fetch.intValue();
					}
				};
				RunnableFuture<Integer> runnableFuture = new FutureTask<Integer>(callable);
				try {
					semaphore.acquire();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				fastExecutor.execute(runnableFuture);// releases semaphore
				futures.add(runnableFuture);
				runnableFuture.get() ;
			}
			assert semaphore.availablePermits() >= 10;
			for(File tempVoiceRecordFile : recordFileList) {
				UKTools.packageVoiceRecordFile(tempVoiceRecordFile, zipOutputStream);
				if(tempVoiceRecordFile!=null && tempVoiceRecordFile.exists()) {
					tempVoiceRecordFile.deleteOnExit();
				}
			}
		}catch(Exception ex) {
			ex.printStackTrace();
		}finally {
			if(byteArrayOutputStream!=null){
            	byteArrayOutputStream.close() ;
            }
			if(zipOutputStream!=null) {
				zipOutputStream.close();
			}
	        if(byteArrayOutputStream!=null){
	        	fileOutputStream.write(byteArrayOutputStream.toByteArray()) ;
	        }
	        if(fileOutputStream!=null) {
				fileOutputStream.close();
			}
		}
		return tempFile;
	}
	
	/**
	 * 检查是否启用通话ACL
	 * @param ip
	 * @param domain
	 * @param pbxhost
	 * @param caller
	 * @param called
	 * @return
	 */
	public static boolean callCheck(String ip ,String domain , PbxHost pbxhost , String caller , String called) {
		IP ipdata = null ;
		boolean kill = false ;
		if(pbxhost != null && pbxhost.isEnableacl() && !StringUtils.isBlank(ip) && !StringUtils.isBlank(domain) && !StringUtils.isBlank(caller) && !StringUtils.isBlank(called)){
			ipdata = IPTools.getInstance().findGeography(ip);
			PbxHost pbxHost = CallCenterUtils.pbxhost(domain);
			if(pbxHost!=null) {
				if ((pbxHost.getMinnumlength() > 0 && caller.length() < pbxHost.getMinnumlength())		//号码（主叫/被叫）超过号码最大长度或小于号码最小长度禁止呼叫，同时禁止IP呼叫
						|| pbxHost.getMaxnumlength() > 0 && caller.length() > pbxHost.getMaxnumlength()
						|| (pbxHost.getMinnumlength() > 0 && called.length() < pbxHost.getMinnumlength())
						|| (pbxHost.getMaxnumlength() > 0 && called.length() > pbxHost.getMaxnumlength())) {
					kill = true ;
				} else if (ipdata != null && !StringUtils.isBlank(pbxHost.getIpregionblack())			//发起呼叫的客户端IP地址所在的地区在黑名单列表中的 ， 禁止呼叫
						&& (pbxHost.getIpregionblack().indexOf(ipdata.getCountry()) >= 0
						|| pbxHost.getIpregionblack().indexOf(ipdata.getCity()) >= 0
						|| pbxHost.getIpregionblack().indexOf(ipdata.getProvince()) >= 0)) {
					kill = true ;
				} else if (ipdata != null && !StringUtils.isBlank(pbxHost.getIpregionwhite()) 			//发起呼叫的客户端IP地址所在的地区在白名单列表中的，允许呼叫，其他禁止呼叫
						&& (pbxHost.getIpregionwhite().indexOf(ipdata.getCountry()) < 0
						&& pbxHost.getIpregionwhite().indexOf(ipdata.getCity()) < 0
						&& pbxHost.getIpregionwhite().indexOf(ipdata.getProvince()) < 0)) {
					kill = true ;
				}
			}
    	}
		return kill ;
	}

	/**
	 *
	 * @param sipTrunk
	 * @param dial_number
	 * @param strb
	 * @return
	 */
	public static String processPhoneNumber(SipTrunk sipTrunk , String dial_number , StringBuffer strb , boolean prefix) {
		if(sipTrunk!=null && "1".equals(sipTrunk.getPrefix()) && !StringUtils.isBlank(sipTrunk.getCity())) {
			MobileAddress address = MobileNumberUtils.getAddress(dial_number) ;
			SysDic dic = UKeFuDic.getInstance().getDicItem(sipTrunk.getCity()) ;
			//启用了异地号码前加拨0
			if(address!=null && dial_number.startsWith("1")) {
				if(!MobileNumberUtils.isSameAreacode(dic.getName(), address) && !(dic!= null && (dic.getName().equals(address.getCity()) || dic.getName().indexOf(address.getCity()) >= 0))) {
					dial_number = "0"+dial_number ;
					strb.append("prefix=").append("true").append(",") ;
				}
			}else if(dial_number.length() > 10 && dial_number.startsWith("2")) {
				dial_number = dial_number.substring(1) ;
			}
		}
		if(sipTrunk!=null && "1".equals(sipTrunk.getPrefix()) && !StringUtils.isBlank(sipTrunk.getPrefixstr()) && prefix) {
			/**
			 * 默认只外线加拨 , 如果加了正则规则，则验证符合正则规则加拨9
			 */
			dial_number = sipTrunk.getPrefixstr()+dial_number ;
		}
		return dial_number ;
	}

    /**
     * 随机获取一个呼出号码
     * @param extno
     * @param ip
     * @param orgi
     * @param pbxHostRes
     * @param extRes
     * @param numberPoolRepository
     * @return
     */
	public static String getNumber(String extno ,String ip ,String orgi, PbxHostRepository pbxHostRes, ExtentionRepository extRes, NumberPoolRepository numberPoolRepository){
        List<PbxHost> pbxHostList = pbxHostRes.findByHostnameOrIpaddr(ip, ip) ;
        PbxHost pbxHost = null;
        if(pbxHostList!=null && pbxHostList.size() > 0) {
            pbxHost = pbxHostList.get(0) ;
        }
        if(pbxHost != null){
            List<Extention> extList = extRes.findByHostidAndExtentionAndOrgi(pbxHost.getId(),extno, orgi) ;
            if(extList.size() > 0){
                Extention ext = extList.get(0) ;
                if(ext != null){
                    List<NumberPool> numberPoolList = numberPoolRepository.findByExtentionid(ext.getId());
                    if(numberPoolList != null && numberPoolList.size() > 0){
                        Random random = new Random();
                        int i = random.nextInt(numberPoolList.size());
                        //随机获取一个呼出号码
                        return numberPoolList.get(i).getNumber();
                    }
                }
            }
        }
		return "";
	}
	
	/**
	 *  获取当前登录用户的可以看到的联系人项目
	 * @param user
	 * @param orgi
	 * @return
	 */
   public static List<ContactsItem> getContactsItem(final User user,final String orgi) {
	   ContactsItemRepository contactsItemRes = UKDataContext.getContext().getBean(ContactsItemRepository.class);
	   ContactsItemAuthorizeRepository contactsItemAuthorizeRes = UKDataContext.getContext().getBean(ContactsItemAuthorizeRepository.class);
    	List<ContactsItem> allItemList = contactsItemRes.findByOrgiAndParentidIsNotNullOrderByCreatetimeDesc(orgi);
    	if (user.isSuperuser()) {
			return allItemList ;
		}else {
			List<ContactsItem> contactsItemList = new ArrayList<ContactsItem>();
			List<ContactsItemAuthorize> authList = contactsItemAuthorizeRes.findByUseridAndOrgiAndDatastatus(user.getId(),orgi ,false) ;
			if (allItemList != null && allItemList.size() > 0) {
				for(ContactsItem item : allItemList) {
					if (item.getCreater().equals(user.getId())) {//自己创建的直接放入
						contactsItemList.add(item) ;
					}else {
						if (authList != null && authList.size() > 0) {//判断授权
							for(ContactsItemAuthorize authorize : authList) {
								if (item.getId().equals(authorize.getItemid()) && !item.getCreater().equals(user.getId()) && !StringUtils.isBlank(item.getParentid())) {//若权限表有此项目且不是自己创建
									contactsItemList.add(item) ;//先把项目放入
								}
							}
						}
					}
				}
			}
			return contactsItemList ;
		}
	}
   
   /**
    * 组装语音渠道中通话记录的查询条件
    * @return
    */
	public static List<Predicate> getSearch(Root<?> root ,CriteriaBuilder cb ,ModelMap map ,@Valid String orgi ,@Valid final String discaller , @Valid final String discalled 
   		, @Valid final String begin , @Valid final String end , @Valid final String direction, @Valid final String userid, @Valid final String organ
			,@Valid final String ringdurbegin ,@Valid final String ringdurend ,@Valid final String incallbegin ,@Valid final String incallend
   		,@Valid final String record ,@Valid final String misscall ,@Valid final String calltype,@Valid final String recordbegin,@Valid final String recordend ,String searchType , HttpServletRequest request ,final String ownerid){
		List<Predicate> list = new ArrayList<Predicate>();  
		
		if(!StringUtils.isBlank(searchType)){
			if("userid".equals(searchType)){
				//只查询当前登录坐席的通话
				list.add(cb.equal(root.get("userid").as(String.class), ownerid)) ;
			}else{
				if(!StringUtils.isBlank(userid)){
					list.add(cb.equal(root.get("userid").as(String.class), userid)) ;
				}
			}
		}else{
			if(!StringUtils.isBlank(userid)){
				list.add(cb.equal(root.get("userid").as(String.class), userid)) ;
			}
		}
		
		if(!StringUtils.isBlank(discaller)){
			list.add(cb.equal(root.get("discaller").as(String.class), discaller)) ;
		}
		list.add(cb.equal(root.get("orgi").as(String.class), orgi)) ;
		if(!StringUtils.isBlank(discalled)){
			list.add(cb.equal(root.get("discalled").as(String.class), discalled)) ;
		}
		if(!StringUtils.isBlank(direction)){
			list.add(cb.equal(root.get("direction").as(String.class), direction)) ;
		}
		
		if(!StringUtils.isBlank(organ)){
			list.add(cb.equal(root.get("organ").as(String.class), organ)) ;
		}
		try {
			if(!StringUtils.isBlank(begin) && begin.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
				list.add(cb.greaterThan(root.get("createtime").as(Date.class), UKTools.dateFormate.parse(begin))) ;
			}
			if(!StringUtils.isBlank(end) && end.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
				list.add(cb.lessThan(root.get("createtime").as(Date.class), UKTools.dateFormate.parse(end))) ;
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		//振铃时长
		if(!StringUtils.isBlank(ringdurbegin)){
			list.add(cb.greaterThan(root.get("ringduration").as(int.class), Integer.parseInt(ringdurbegin)*1000)) ;
		}
		if(!StringUtils.isBlank(ringdurend)){
			list.add(cb.lessThan(root.get("ringduration").as(int.class), Integer.parseInt(ringdurend)*1000)) ;
		}
		
		//通话时长
		if(!StringUtils.isBlank(incallbegin)){
			list.add(cb.greaterThan(root.get("duration").as(int.class), Integer.parseInt(incallbegin)*1000)) ;
		}
		if(!StringUtils.isBlank(incallend)){
			list.add(cb.lessThan(root.get("duration").as(int.class), Integer.parseInt(incallend)*1000)) ;
		}
		
		//录音时长
		if(!StringUtils.isBlank(recordbegin)){
			list.add(cb.greaterThan(root.get("recordtime").as(int.class), Integer.parseInt(recordbegin)*1000)) ;
		}
		if(!StringUtils.isBlank(recordend)){
			list.add(cb.lessThan(root.get("recordtime").as(int.class), Integer.parseInt(recordend)*1000)) ;
		}
		
		//是否录音
		if(!StringUtils.isBlank(record)){
			list.add(cb.equal(root.get("record").as(boolean.class), Boolean.valueOf(record))) ;
		}
		
		//是否漏话
		if(!StringUtils.isBlank(misscall)){
			list.add(cb.equal(root.get("misscall").as(boolean.class), Boolean.valueOf(misscall))) ;
		}
		
		//呼叫方向
		if(!StringUtils.isBlank(calltype)){
			list.add(cb.equal(root.get("calltype").as(String.class), calltype)) ;
		}
		
		//满意度评价
		if(!StringUtils.isBlank(request.getParameter("satisfaction"))){
			if("not".equals(request.getParameter("satisfaction"))){
				list.add(cb.isNull(root.get("satisfaction").as(String.class))) ;
			}else{
				list.add(cb.equal(root.get("satisfaction").as(String.class), request.getParameter("satisfaction"))) ;
			}
			map.addAttribute("satisfaction", request.getParameter("satisfaction"));
		}
		
		//质检时间
		try {
			if(!StringUtils.isBlank(request.getParameter("beginqualitytime")) && request.getParameter("beginqualitytime").matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
				list.add(cb.greaterThan(root.get("qualitytime").as(Date.class), UKTools.dateFormate.parse(request.getParameter("beginqualitytime")))) ;
			}
			if(!StringUtils.isBlank(request.getParameter("endqualitytime")) && request.getParameter("endqualitytime").matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
				list.add(cb.lessThan(root.get("qualitytime").as(Date.class), UKTools.dateFormate.parse(request.getParameter("endqualitytime")))) ;
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		return list;
	}
	
	/**
	 * 
	 * 
	 * @param pbxHost
	 * @param dial_number
	 * @return
	 */
	public static String processPhoneNumber(PbxHost pbxHost , String dial_number) {
		String process_dial_number = dial_number ;
		if(pbxHost!=null && pbxHost.isEnablereplace() && !StringUtils.isBlank(pbxHost.getReplacereg())) {
			String[] replacereg = pbxHost.getReplacereg().split("\\|") ;
			String[] replacestr = null ;
			if(!StringUtils.isBlank(pbxHost.getReplacestr())) {
				replacestr = pbxHost.getReplacestr().split("\\|") ;
			}
			if(replacereg.length > 0) {
				for(int i = 0 ; i < replacereg.length ; i++) {
					String replace = "" ;
					if(replacestr!=null && replacestr.length > i) {
						replace = replacestr[i] ;
					}
					if(replace!=null) {
						process_dial_number = dial_number.replace(replacereg[i], replace) ;
					}
				}
			}
		}
		return process_dial_number ;
	}
	
	
	public static List<Predicate> getSearchData(Root<?> root ,CriteriaBuilder cb ,ModelMap map ,HttpServletRequest request ,String orgi ,@Valid SearchData searchData ,String searchType ,final String ownerid){
		List<Predicate> list = new ArrayList<Predicate>();  
		list.add(cb.equal(root.get("orgi").as(String.class), orgi)) ;
		if(!StringUtils.isBlank(searchType)){
			if("userid".equals(searchType)){
				//只查询当前登录坐席的通话
				list.add(cb.equal(root.get("userid").as(String.class), ownerid)) ;
			}else{
				if(!StringUtils.isBlank(searchData.getUserid())){
					list.add(cb.equal(root.get("userid").as(String.class), searchData.getUserid())) ;
				}
			}
		}else{
			if(!StringUtils.isBlank(searchData.getUserid())){
				list.add(cb.equal(root.get("userid").as(String.class), searchData.getUserid())) ;
			}
		}
		
		if(!StringUtils.isBlank(searchData.getDiscaller())){
			list.add(cb.or(cb.equal(root.get("discaller").as(String.class), searchData.getDiscaller()),
					cb.and(cb.equal(root.get("hidetype").as(String.class), UKDataContext.CallTypeEnum.IN.toString()),cb.equal(root.get("priphone").as(String.class), searchData.getDiscaller())))) ;
		}
		if(!StringUtils.isBlank(searchData.getDiscalled())){
			list.add(cb.or(cb.equal(root.get("discalled").as(String.class), searchData.getDiscalled()),
					cb.and(cb.equal(root.get("hidetype").as(String.class), UKDataContext.CallTypeEnum.OUT.toString()),cb.equal(root.get("priphone").as(String.class), searchData.getDiscalled())))) ;
		}
		if(!StringUtils.isBlank(searchData.getDirection())){
			list.add(cb.equal(root.get("direction").as(String.class), searchData.getDirection())) ;
		}
		
		if(!StringUtils.isBlank(searchData.getOrgan())){
			list.add(cb.equal(root.get("organ").as(String.class), searchData.getOrgan())) ;
		}
		try {
			if(!StringUtils.isBlank(searchData.getBegin()) && searchData.getBegin().matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
				list.add(cb.greaterThan(root.get("createtime").as(Date.class), UKTools.dateFormate.parse(searchData.getBegin()))) ;
			}
			if(!StringUtils.isBlank(searchData.getEnd()) && searchData.getEnd().matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
				list.add(cb.lessThan(root.get("createtime").as(Date.class), UKTools.dateFormate.parse(searchData.getEnd()))) ;
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		//振铃时长
		if(!StringUtils.isBlank(searchData.getRingdurbegin())){
			list.add(cb.greaterThan(root.get("ringduration").as(int.class), Integer.parseInt(searchData.getRingdurbegin())*1000)) ;
		}
		if(!StringUtils.isBlank(searchData.getRingdurend())){
			list.add(cb.lessThan(root.get("ringduration").as(int.class), Integer.parseInt(searchData.getRingdurend())*1000)) ;
		}
		
		//通话时长
		if(!StringUtils.isBlank(searchData.getIncallbegin())){
			list.add(cb.greaterThan(root.get("duration").as(int.class), Integer.parseInt(searchData.getIncallbegin())*1000)) ;
		}
		if(!StringUtils.isBlank(searchData.getIncallend())){
			list.add(cb.lessThan(root.get("duration").as(int.class), Integer.parseInt(searchData.getIncallend())*1000)) ;
		}
		
		//录音时长
		if(!StringUtils.isBlank(searchData.getRecordbegin())){
			list.add(cb.greaterThan(root.get("recordtime").as(int.class), Integer.parseInt(searchData.getRecordbegin())*1000)) ;
		}
		if(!StringUtils.isBlank(searchData.getRecordend())){
			list.add(cb.lessThan(root.get("recordtime").as(int.class), Integer.parseInt(searchData.getRecordend())*1000)) ;
		}
		
		//是否录音
		if(!StringUtils.isBlank(searchData.getRecord())){
			list.add(cb.equal(root.get("record").as(boolean.class), Boolean.valueOf(searchData.getRecord()))) ;
		}
		
		//是否漏话
		if(!StringUtils.isBlank(searchData.getMisscall())){
			list.add(cb.equal(root.get("misscall").as(boolean.class), Boolean.valueOf(searchData.getMisscall()))) ;
		}
		
		//呼叫方向
		if(!StringUtils.isBlank(searchData.getCalltype())){
			list.add(cb.equal(root.get("calltype").as(String.class), searchData.getCalltype())) ;
		}
		
		//队列，技能组
		if(!StringUtils.isBlank(searchData.getQuene())){
			list.add(cb.equal(root.get("quene").as(String.class), searchData.getQuene())) ;
		}
		
		if(!StringUtils.isBlank(searchData.getId())){
			list.add(cb.equal(root.get("id").as(String.class), searchData.getId())) ;
		}
		
		if(!StringUtils.isBlank(searchData.getExtnum())){
			list.add(cb.or(cb.equal(root.get("discaller").as(String.class), searchData.getExtnum()),cb.equal(root.get("discalled").as(String.class), searchData.getExtnum()))) ;
		}
		
		//满意度评价
		if(!StringUtils.isBlank(searchData.getSatisfaction())){
			if("not".equals(searchData.getSatisfaction())){
				list.add(cb.isNull(root.get("satisfaction").as(String.class))) ;
			}else{
				list.add(cb.equal(root.get("satisfaction").as(String.class), searchData.getSatisfaction())) ;
			}
		}
		
		//质检评分
		if(!StringUtils.isBlank(searchData.getQualityscore())){
			list.add(cb.equal(root.get("qualityscore").as(String.class), searchData.getQualityscore())) ;
		}
		
		map.addAttribute("discaller", searchData.getDiscaller()) ;
		map.addAttribute("discalled", searchData.getDiscalled()) ;
		map.addAttribute("begin", searchData.getBegin()) ;
		map.addAttribute("end",  searchData.getEnd()) ;
		map.addAttribute("organ",  searchData.getOrgan()) ;
		map.addAttribute("userid",  searchData.getUserid()) ;
		map.addAttribute("ringdurbegin", searchData.getRingdurbegin()) ;
		map.addAttribute("ringdurend", searchData.getRingdurend()) ;
		map.addAttribute("incallbegin", searchData.getIncallbegin()) ;
		map.addAttribute("incallend", searchData.getIncallend()) ;
		map.addAttribute("record", searchData.getRecord()) ;
		map.addAttribute("misscall", searchData.getMisscall()) ;
		map.addAttribute("calltype", searchData.getCalltype()) ;
		map.addAttribute("recordbegin", searchData.getRecordbegin()) ;
		map.addAttribute("recordend", searchData.getRecordend()) ;
		map.addAttribute("quene", searchData.getQuene()) ;
		map.addAttribute("id", searchData.getId()) ;
		map.addAttribute("extnum", searchData.getExtnum()) ;
		map.addAttribute("satisfaction", searchData.getSatisfaction());
		map.addAttribute("qualityscore", searchData.getQualityscore());
		
		//语音平台中的技能组（队列）
		CallCenterSkillRepository callCenterSkillRepository = UKDataContext.getContext().getBean(CallCenterSkillRepository.class);
		List<CallCenterSkill> callCenterSkillList = callCenterSkillRepository.findByOrgi(orgi);
		map.addAttribute("callCenterSkillList", callCenterSkillList) ;
		
		//用户列表
		UserRepository userRes = UKDataContext.getContext().getBean(UserRepository.class) ;
		map.put("allUserList",userRes.findByOrgiAndDatastatus(orgi, false));
		
		//部门列表
		OrganRepository organRes = UKDataContext.getContext().getBean(OrganRepository.class) ;
		User user = getUser(request);
		if ((!StringUtils.isBlank(user.getUsertype()) && !user.getUsertype().equals("0")) || StringUtils.isBlank(user.getUsertype())) {
			List<String> organList = CallCenterUtils.getExistOrgan(user);
			In<Object> in = cb.in(root.get("organ"));
			if(organList.size() > 0){
				for(String id : organList){
					in.value(id) ;
				}
			}else{
				in.value(UKDataContext.UKEFU_SYSTEM_NO_DAT) ;
			}	
			if (StringUtils.isBlank(searchType) || (!StringUtils.isBlank(searchType) && !"userid".equals(searchType))) {
				list.add(in) ;
			}
			map.put("skillList",organRes.findAll(organList));
			map.put("allUserList",userRes.findByOrganInAndDatastatusAndOrgi(organList, false, orgi));
		}else{
			map.put("skillList",organRes.findByOrgi(orgi));
		}
		return list;
	}
	
	public static User getUser(HttpServletRequest request){
		User user = (User) request.getSession(true).getAttribute(UKDataContext.USER_SESSION_NAME)  ;
		if(user==null){
			String authorization = request.getHeader("authorization") ;
			if(StringUtils.isBlank(authorization) && request.getCookies()!=null){
				for(Cookie cookie : request.getCookies()){
					if(cookie.getName().equals("authorization")){
						authorization = cookie.getValue() ; break ;
					}
				}
			}
			if(!StringUtils.isBlank(authorization)){
				user = (User) CacheHelper.getApiUserCacheBean().getCacheObject(authorization, UKDataContext.SYSTEM_ORGI) ;
			}
			if(user==null){
				user = new User();
				user.setId(UKTools.getContextID(request.getSession().getId())) ;
				user.setUsername(UKDataContext.GUEST_USER+"_"+UKTools.genIDByKey(user.getId())) ;
				user.setOrgi(UKDataContext.SYSTEM_ORGI);
				user.setSessionid(user.getId()) ;
			}
		}else{
			user.setSessionid(user.getId()) ;
		}
		return user ;
	}
}
